#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 4096 // 4k
#define M SIZE
#define N SIZE

// 初始化一个大矩阵
void initialize_matrix(float **mat)
{
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            mat[i][j] = (float)(i * N + j); // 初始化数据
        }
    }
}

int main()
{
    // 动态分配内存处理大矩阵
    float *A = (float *)malloc(M * N * sizeof(float));
    if (A == NULL)
    {
        printf("Failed to allocate memory");
        return 1;
    }

    // 仅对矩阵A进行读取操作,并通过求和操作来避免编译器完全跳过循环
    volatile float sum = 0.0f;
    clock_t start, end;
    double cpu_time_used;

    // 1.按行读取
    printf("按行读取数据：\n");
    start = clock();

    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            sum += A[i * N + j]; // 访问A[I][J]
        }
    }

    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("按行读取数据花费的时间为：%f秒", cpu_time_used);
    printf("总和：%f\n\n", sum);
    // 按行读取数据花费的时间为：0.046000秒

    // 2.按列读取数据
    printf("--- 开始按列读取测试 (预计更慢) ---\n");
    sum = 0.0f; // 重置 sum
    start = clock();

    for (int j = 0; j < N; j++)
    { // 外层循环是列
        for (int i = 0; i < M; i++)
        {                        // 内层循环是行
            sum += A[i * N + j]; // 访问 A[i][j]
        }
    }

    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("按列读取时间: %f 秒\n", cpu_time_used);
    printf("总和（仅为防止优化）：%f\n", sum);
    // 按列读取时间: 0.201000 秒

    free(A); // 释放内存
    return 0;
    /*
    运行结果：
    1.按行读取数据花费的时间为：0.046000秒
    2.按列读取时间: 0.201000 秒
    可以得到结论：按行读取数据明显快于按列读取数据。这是因为内存是按行优先存储的，按行访问时数据局部性更好，缓存命中率更高，从而提高了访问速度。
    */
}
